/*
 * Copyright 2012 Sergey Netesanyi.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.versatile.gwt.serialization.client.stream;

import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.impl.Serializer;
import com.versatile.gwt.serialization.client.Constants;

/**
 * {@link SerializationStreamReader} implementation to serialize objects to string on the client side.
 *
 * @author Sergey Netesanyi
 * @version 1.0
 */
public class StringSerializationStreamReader implements SerializationStreamReader {
    /** Serializer object. */
    private Serializer serializer;
    /** Stream object. */
    private String stream;
    /** Stream position. */
    private int index = 0;

    public StringSerializationStreamReader(Serializer serializer) {
        this.serializer = serializer;
    }

    public void prepare(String stream) {
        index = 0;
        this.stream = stream;
    }

    /** {@inheritDoc} */
    @Override
    public boolean readBoolean() throws SerializationException {
        return Boolean.parseBoolean(readNext());
    }

    private String readNext() {
        int end = stream.indexOf(Constants.SEPARATOR, index);
        String result = stream.substring(index, end);
        index = end + 2;
        return result;
    }

    /** {@inheritDoc} */
    @Override
    public byte readByte() throws SerializationException {
        return Byte.parseByte(readNext());
    }

    /** {@inheritDoc} */
    @Override
    public char readChar() throws SerializationException {
        return readNext().charAt(0);
    }

    /** {@inheritDoc} */
    @Override
    public double readDouble() throws SerializationException {
        return Double.parseDouble(readNext());
    }

    /** {@inheritDoc} */
    @Override
    public float readFloat() throws SerializationException {
        return Float.parseFloat(readNext());
    }

    /** {@inheritDoc} */
    @Override
    public int readInt() throws SerializationException {
        return Integer.parseInt(readNext());
    }

    /** {@inheritDoc} */
    @Override
    public long readLong() throws SerializationException {
        return Long.parseLong(readNext());
    }

    /** {@inheritDoc} */
    @Override
    public Object readObject() throws SerializationException {

        String signatureType = readString();
        if (signatureType == null || signatureType.isEmpty()) return null;

        Object object = serializer.instantiate(this, signatureType);
        serializer.deserialize(this, object, signatureType);

        return object;
    }

    /** {@inheritDoc} */
    @Override
    public short readShort() throws SerializationException {
        return Short.parseShort(readNext());
    }

    /** {@inheritDoc} */
    @Override
    public String readString() throws SerializationException {
        return readNext();
    }
}
